package com.apes.enquiry.voluntaryOffers.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.enquiry.brand.model.SpBrand;
import com.apes.enquiry.brand.repository.SpBrandRepository;
import com.apes.enquiry.enquiry.model.Enquiry;
import com.apes.enquiry.enquiry.model.EnquiryItem;
import com.apes.enquiry.enquiry.model.Quote;
import com.apes.enquiry.enquiry.model.QuoteResult;
import com.apes.enquiry.enquiry.repository.EnquiryItemRepository;
import com.apes.enquiry.enquiry.repository.EnquiryRepository;
import com.apes.enquiry.enquiry.repository.QuoteRepository;
import com.apes.enquiry.enquiry.repository.QuoteResultRepository;
import com.apes.enquiry.product.model.*;
import com.apes.enquiry.product.repository.AutomobileBrandRepository;
import com.apes.enquiry.product.repository.SpCategoryRepository;
import com.apes.enquiry.product.repository.SpProductRepository;
import com.apes.enquiry.supplier.baturu.BaturuApi;
import com.apes.enquiry.supplier.baturu.model.BaturuInquire;
import com.apes.enquiry.supplier.baturu.repository.BaturuAccountInfoRepository;
import com.apes.enquiry.supplier.baturu.repository.BaturuInquireRepository;
import com.apes.enquiry.supplier.baturu.service.BaturuAccountInfoService;
import com.apes.enquiry.voluntaryOffers.dto.BaturuQuoteResultDto;
import com.apes.enquiry.voluntaryOffers.dto.Parts;
import com.apes.enquiry.voluntaryOffers.dto.Prices;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.Tools;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apestech.framework.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class MatchingRuleService extends DomainService {
    @Autowired
    private MatchingRuleDao matchingRuleDao;

    @Autowired
    private SpProductRepository spProductRepository;

    @Autowired
    private AutomobileBrandRepository automobileBrandRepository;

    @Autowired
    private SpBrandRepository spBrandRepository;

    @Autowired
    private EnquiryRepository enquiryRepository;
    @Autowired
    private QuoteResultRepository quoteResultRepository;
    @Autowired
    private EnquiryItemRepository enquiryItemRepository;
    @Autowired
    private QuoteRepository quoteRepository;
    @Autowired
    private BaturuApi baturuApi;
    @Autowired
    private BaturuAccountInfoRepository baturuAccountInfoRepository;
    @Autowired
    private BaturuInquireRepository baturuInquireRepository;
    @Autowired
    private BaturuAccountInfoService baturuAccountInfoService;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private BusinessParamRepository businessParamRepository;


    /**
     * 过滤掉没有意义的商品（没有系统报价、没有价格）
     *
     * @param request {"category":"配件名称", "OE":"OE号", "PZCXID":"配置车型ID"}
     * @return 可系统报价且有价格的商品
     */
    public List meaningfulProduct(SimpleRequest request) {
        JSONObject json = request.getJO();
        List<Map> full = new ArrayList<>();

        Set<SpProduct> allProduct = new HashSet<>();//匹配商品结果集
        //判断是标准名称还是OE号匹配
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(json.getString("category"))) {
            Category category = SpringManager.getBean(SpCategoryRepository.class).findOne(json.getString("category"));
            request.setData(MapUtil.mapper("category", category, "PZCXID", json.getString("PZCXID")));
            //商品匹配
            allProduct.addAll(compile(request));
        }
        //判断是否有OE号，有OE号再匹配一次商品
        if (json.containsKey("OE")) {
            request.setData(MapUtil.mapper("PZCXID", json.getString("PZCXID"), "OE", json.getString("OE")));
            allProduct.addAll(compile(request));
        }
        //过滤商品
        List<SpProduct> spProducts = allProduct.stream().filter(SpProduct::offer).filter(SpProduct::notTaxUnitPrice).filter(SpProduct::merchantStockQty).collect(Collectors.toList());
        List<Map> maps = this.extractSpProducts(spProducts);
        full.addAll(maps);

        return full;
    }

    /**
     * 智选配件不匹配搜索供应商商品
     *
     * @param request
     * @return
     */
    public List extendProduct(SimpleRequest request) {
        JSONObject json = request.getJO();
        List<Map> full = new ArrayList<>();
        String name = json.getString("name");
        List<SpProduct> spProducts = new ArrayList<>();
        if (name.indexOf("蓄电池")!=-1 || name.indexOf("电池")!=-1){
             spProducts = spProductRepository.findbyNameAndAccumulator("%"+name+"%");
        }

        if (name.indexOf("油")!=-1){
            spProducts = spProductRepository.findbyNameAndOily("%"+name+"%");
        }

        if (name.indexOf("轮胎")!=-1){
            spProducts = spProductRepository.findbyNameAndTyre("%"+name+"%");
        }
        if(spProducts.isEmpty()){
            spProducts = spProductRepository.findbyNameAndTyre("%"+name+"%");
            if(!spProducts.isEmpty()){
                String type = spProducts.get(0).getType();
                spProducts =  spProducts.stream().filter(item-> type.equals(item.getType())).collect(Collectors.toList());
            }
        }
        List<Map> maps = this.extractSpProducts(spProducts);
        full.addAll(maps);
        return full;
    }


    /**
     * 闪电报价获取供应商平台商品
     *
     * @param request
     * @return
     */
    public List lightningOffer(SimpleRequest request) {
        JSONObject json = request.getJO();
        List<Map> mapList = new ArrayList<>();

        //获取巴图鲁供应商id，用来排除巴图鲁过期商品
        BusinessParam supplierNumber = businessParamRepository.findAllByQueryKey("baturuSupplierNumber").get(0);
        String[] split = supplierNumber.getValue().replace("[", "").replace("]", "").split(",");

        List<Enquiry> enquiries = enquiryRepository.findByServicePlanId(json.getString("dept"), json.getString("VIN"));
        //过滤巴图鲁过期报价商品
        for (Enquiry enquiry : enquiries) {
            List<QuoteResult> newQuoteResults = new ArrayList<>();
            List<QuoteResult> quoteResults = quoteResultRepository.findByEnquiryId(enquiry.getId());
            if (!CollectionUtils.isEmpty(quoteResults)){
                quoteResults.forEach(item -> {
                    if (split[0].equals(item.getSupplierId())){
                        if (!ObjectUtils.isEmpty(item.getExpiredTime()) && item.getExpiredTime().getTime() <= new Date().getTime()){
                            return;
                        }
                    }
                    newQuoteResults.add(item);
                });
            }
            //获取询价结果 报价结果 商品
            mergePrice(mapList, newQuoteResults, enquiry);
        }
        List<Map> products = new ArrayList<>();
        //根据商品进行分组
        productGroup(mapList, products);

        return products;
    }

    @OutboxSubscriber(id = "local:baturuInquireService.baturuNoticeObtainInquiryOutbox", name = "巴图鲁通知需要获取报价")
    private void baturuNoticeObtainInquiryOutbox(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject getJO = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String inquiryNo = getJO.getString("data");
        BaturuInquire baturuInquire = baturuInquireRepository.accordBaturuInquiryIdFind(inquiryNo);
        String userKey = baturuAccountInfoService.queryUserKey(baturuInquire.getStore());
        Quote quote = quoteRepository.findByModelId(inquiryNo);
        saveQuoteResult(userKey, quote);
    }

    /**
     * 获取并保存巴图鲁报价结果
     * @param userKey
     * @param quote
     */
    public void saveQuoteResult(String userKey, Quote quote){
        JSONObject request = new JSONObject();
        request.put("userKey", userKey);
        request.put("inquiryNo", quote.getModelId());
        request.put("invoiceType", -1);
        JSONObject result = baturuApi.queryQuote(request);

        BusinessParam supplierNumber = businessParamRepository.findAllByQueryKey("baturuSupplierNumber").get(0);
        String[] split = supplierNumber.getValue().replace("[", "").replace("]", "").split(",");
        if (!ObjectUtils.isEmpty(result.getJSONObject("model"))) {
            BaturuQuoteResultDto dto = Tools.map(result.getJSONObject("model"), BaturuQuoteResultDto.class);
            List<Parts> parts = dto.getParts();

            // 更新报价时间
            if (ObjectUtils.isEmpty(quote.getFirstQuoteDate())){
                quote.setFirstQuoteDate(new Date());
                quote.setState("finish");
            }
            quote.setUpdateQuoteDate(new Date());
            quoteRepository.saveAndFlush(quote);

            // 存在一个价格都没有返回的情况，更新已有的有效标标记
            boolean partsIsEmptyFlag = CollectionUtils.isEmpty(parts);
            if (partsIsEmptyFlag) {
                this.updateQuoteValid(partsIsEmptyFlag, new HashSet<>(), quote.getId());
                return;
            }

            //判断是否第一次报价，若不是第一次将之前的报价结果标识改为旧的
            List<QuoteResult> quoteResults = quoteResultRepository.findByQuoteId(quote.getId());
            if (!CollectionUtils.isEmpty(quoteResults)){
                quoteResultRepository.updateFlagByQuoteId(quote.getId());
            }

            Set<String> priceNos = new HashSet<>();
            for (int i = 0; i < parts.size(); i++) { // parts 询价配件
                Parts part = parts.get(i);
                if (StringUtils.isEmpty(part.getPartsId())) continue; // 巴图鲁直接自己添加报价，此时无 partsId

                // 报价配件价格列表
                List<Prices> prices = part.getPrices();
                for (int p = 0; p < prices.size(); p++) {
                    Prices price = prices.get(p);

                    // 拼接报价结果
                    QuoteResult quoteResult = this.appenQuoteResult(price, quote, part, split, dto);
                    quoteResultRepository.saveAndFlush(quoteResult);

                    priceNos.add(price.getPriceNo());
                }
            }

            // 更新报价有效标记
            this.updateQuoteValid(false, priceNos, quote.getId());
        }
    }


    private QuoteResult appenQuoteResult(Prices price, Quote quote, Parts part, String[] split, BaturuQuoteResultDto dto) {
        //获取品牌和商品
        SpBrand brand = getSpBrand(price);
        SpProduct product = getSpProduct(price, brand, part.getModifiedPartsName(), split[0]);
        QuoteResult quoteResult = new QuoteResult();
        quoteResult.setQuoteId(quote.getId());
        quoteResult.setEnquiryId(quote.getEnquiryId());
        quoteResult.setEnquiryItem(part.getPartsId());
        quoteResult.setQuoteBrand(brand);
        quoteResult.setNotTaxUnitPrice(price.getQuotePriceWithDiscount());
        quoteResult.setTaxUnitPrice(price.getQuotePriceWithDiscount());
        quoteResult.setSupplierId(split[0]);
        quoteResult.setState(price.getIsBookGoods() == 0 ? "00" : "10");
        quoteResult.setNote(price.getRemark());
        quoteResult.setPurchaseInformation(price.getArriveTime());
        quoteResult.setZBQ(price.getGuaranteePeriod());
        quoteResult.setProduct(product);
        quoteResult.setPriceNo(price.getPriceNo());
        quoteResult.setExpiredTime(new Date(dto.getExpiredTime()));
        quoteResult.setLatestFlag(1);
        quoteResult.setQuotaValid(1);
        quoteResult.setQuoteDate(new Date());
        if (ObjectUtils.isEmpty(price.getBookGoodsInfo())){
            quoteResult.setPlaceOfDispatch(0);
        }else {
            quoteResult.setPlaceOfDispatch(price.getBookGoodsInfo().getBookGoodsDays());
        }
        if (!CollectionUtils.isEmpty(price.getSupplierPictures())) {
            JSONArray pngs = new JSONArray();
            price.getSupplierPictures().forEach(item -> {
                JSONObject png = new JSONObject();
                png.put("url", item);
                pngs.add(png);
            });
            quoteResult.setPng(JSONObject.toJSONString(pngs));
        }

        return quoteResult;
    }


    // 失效报价处理
    private void updateQuoteValid(boolean allNotValidFlag, Set<String> priceNos, String quoteResultId) {
        if (!allNotValidFlag && priceNos.isEmpty()) return;
        List<QuoteResult> quoteResults = new ArrayList<>();
        if (allNotValidFlag) { // 全部失效
            quoteResults = quoteResultRepository.findByQuoteId(quoteResultId);
        } else {
            // 排除已存在的 priceNo，其余都需要更新为无效
            quoteResults = quoteResultRepository.findNoInPriceNo(priceNos, quoteResultId);
        }

        if (quoteResults.isEmpty()) return;

        // 更新为无效
        quoteResults.forEach(quoteResult -> quoteResult.setQuotaValid(0));
        quoteResultRepository.saveAll(quoteResults);

        // 更新为有效, 存在第一次报过来有效，第二次无效，第三次有效，此时结果中存在两天无效标记的历史数据
        quoteResults = quoteResultRepository.findAll(JpaDsl.toCriteria("priceNo", "in", priceNos, "quoteId", "eq", quoteResultId));
        quoteResults.forEach(quoteResult -> quoteResult.setQuotaValid(1));
        quoteResultRepository.saveAll(quoteResults);
    }

    /**
     * 获取品牌信息
     * @param price
     * @return
     */
    public SpBrand getSpBrand(Prices price){
        String[] split = price.getBrandName().split("_");
        String brandName = split[0];
        if (StringUtil.isEmpty(brandName)){
            //产地件直接返回
            SpBrand brand = spBrandRepository.findByName("名牌");
            return brand;
        }
        if ("原厂原装".equals(split[0])){
            brandName = "原厂";
        }else if (split[0].contains("进口")){
            brandName = "原厂(进口)";
        }else if (split[0].contains("4S")){
            brandName = "原厂国内(4S店)";
        }else {
            brandName = split[0];
        }
        String replace = brandName.replace("(", "");
        String rKeyword = replace.replace(")", "");
        SpBrand brand = spBrandRepository.findByName(rKeyword);
        if (ObjectUtils.isEmpty(brand)){
            brand = new SpBrand();
            brand.setCreatorName("admin");
            brand.setEntryDate(new Date());
            brand.setName(rKeyword);
            brand.setTime(DateUtil.timeStampToStr(new Date().getTime()));
            brand.setValid(true);
            brand = spBrandRepository.saveAndFlush(brand);
            //brand = spBrandRepository.findByName("其他件");
        }
        return brand;
    }

    /**
     * 获取商品信息
     * @param price
     * @param spBrand
     * @param partName
     * @return
     */
    public SpProduct getSpProduct(Prices price, SpBrand spBrand, String partName,String supplierId){
        PartyRole baturuSupplier = partyRoleRepository.findOne(supplierId);
        SpProduct product = spProductRepository.findBypnAndSpBrand(price.getQuotedPartsCode(),spBrand,baturuSupplier, partName);
        if (ObjectUtils.isEmpty(product)){
            product = new SpProduct();
            product.setName(partName);
            product.setProductState("notOffer");
            product.setMateState("fail");
            product.setSpBrand(spBrand);
            product.setNotTaxUnitPrice(price.getQuotePrice());
            product.setPutawayState(false);
            if (ObjectUtils.isEmpty(spBrand)){
                product.setStandardType("brandWhole");
            }else {
                product.setStandardType(spBrand.getName().contains("原厂")? "Whole":"brandWhole");
            }
            product.setType("巴图鲁商品");
            product.setOE(price.getQuotedPartsCode());
            product.setSupplier(baturuSupplier);
            product.setMerchantProduct(String.valueOf(price.getFranchiseSupplierId()));
            product = spProductRepository.saveAndFlush(product);
        }
        return product;
    }

    /**
     * 根据商品进行分组
     * @param mapList
     * @param products
     */
    private void productGroup(List<Map> mapList, List<Map> products) {
        if (mapList.size() > 0) {
            mapList.stream().forEach(item -> {
                SpProduct spProduct = (SpProduct) item.get("product");
                switch (spProduct.getStandardType()) {//（原厂标准商品:Whole /品牌标准商品：brandWhole /蓄电池：Accumulator /轮胎：Tyre /机油：Oily）
                    case "Accumulator": {
                        AccumulatorProduct accumulatorProduct = spProduct.extend();
                        item.put("extend", accumulatorProduct);
                        products.add(item);
                        break;
                    }
                    case "Tyre": {
                        TyreProduct tyreProduct = spProduct.extend();
                        item.put("extend", tyreProduct);
                        products.add(item);
                        break;
                    }
                    case "Oily": {
                        OilyProduct oilyProduct = spProduct.extend();
                        item.put("extend", oilyProduct);
                        products.add(item);
                        break;
                    }
                    default:
                        item.put("extend", null);
                        products.add(item);
                }
            });
        }
    }

    /**
     * 遍历获取商品、询价结果、报价结果
     * @param mapList
     * @param quoteResults
     */
    private void mergePrice(List<Map> mapList, List<QuoteResult> quoteResults, Enquiry enquiry) {
        for (QuoteResult quoteResult : quoteResults) {
            if (quoteResult.getProduct() == null) continue;
            EnquiryItem enquiryItem = enquiryItemRepository.findOne(quoteResult.getEnquiryItem());
            SpProduct spProduct = spProductRepository.findOne(quoteResult.getProduct().getId());

            //判断配件是否存在，不存在则使用译码临时配件名
            codingExtend(enquiryItem, spProduct, quoteResult);

            Map map = new HashMap();
            map.put("product", spProduct);
            map.put("auoteResult", quoteResult.getId());//报价结果ID
            map.put("enquiry", quoteResult.getEnquiryId());//询价单ID
            map.put("category", enquiryItem.getCategory());//标准名称
            map.put("quoteResult", quoteResult);
            map.put("quoteResultId", quoteResult.getId());
            map.put("brand", MapUtil.mapped(spProduct.getSpBrand()));
            map.put("fourSPrice", enquiryItem.getPrice());
            map.put("productRule", enquiry.getProductRule());
            Quote quote = quoteRepository.findOne(quoteResult.getQuoteId());
            PartyRole supplier = getBean(PartyRoleRepository.class).findOne(quote.getPartyRoleId());
            if (supplier == null) {
                map.put("address", "");
            } else {
                map.put("address", supplier.getParty().getCorporate().getOfficeCity().getName());
            }

            mapList.add(map);
        }
    }

    /**
     * 判断配件名称是否存在，不存在则使用译码临时配件名
     * @param enquiryItem
     * @param spProduct
     */
    private void codingExtend(EnquiryItem enquiryItem, SpProduct spProduct, QuoteResult quoteResult) {
        if (spProduct != null && org.apache.commons.lang3.StringUtils.isNotEmpty(enquiryItem.getCategoryId())) {
            Category category = getBean(SpCategoryRepository.class).findOne(enquiryItem.getCategoryId());
            spProduct.setCategory(category);
        }else {
            Map<String,String> category = new HashMap<>();
            category.put("name", enquiryItem.getCategoryName());
            spProduct.setTransientCategory(category);
        }

        //巴图鲁译码图片
        if (org.apache.commons.lang3.StringUtils.isEmpty(quoteResult.getPng()) && org.apache.commons.lang3.StringUtils.isNotEmpty(enquiryItem.getEpcPicture())){
            quoteResult.setTransientPicture(enquiryItem.getEpcPicture());
        }
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(quoteResult.getPng()) && org.apache.commons.lang3.StringUtils.isNotEmpty(enquiryItem.getEpcPicture())){
            JSONArray arrayPng = JSONArray.parseArray(quoteResult.getPng());
            arrayPng.addAll(JSONArray.parseArray(enquiryItem.getEpcPicture()));
            quoteResult.setTransientPicture(arrayPng.toJSONString());
        }


    }

    /**
     * 遍历商品明细
     *
     * @param spProducts
     * @return
     */
    public List<Map> extractSpProducts(List<SpProduct> spProducts) {
        List<Map> products = new ArrayList<>();
        for (SpProduct product : spProducts) {
            switch (product.getStandardType()) {//（原厂标准商品:Whole /品牌标准商品：brandWhole /蓄电池：Accumulator /轮胎：Tyre /机油：Oily）
                case "Accumulator": {
                    AccumulatorProduct accumulatorProduct = product.extend();
                    products.add(MapUtil.mapper("product", product, "extend", accumulatorProduct, "brand", product.getSpBrand()));
                    break;
                }
                case "Tyre": {
                    TyreProduct tyreProduct = product.extend();
                    products.add(MapUtil.mapper("product", product, "extend", tyreProduct, "brand", product.getSpBrand()));
                    break;
                }
                case "Oily": {
                    OilyProduct oilyProduct = product.extend();
                    products.add(MapUtil.mapper("product", product, "extend", oilyProduct,"brand", product.getSpBrand()));
                    break;
                }
                default:
                    products.add(MapUtil.mapper("product", product, "extend", null, "brand", product.getSpBrand()));
            }
        }
        return products;
    }

    /**
     * 商品匹配查询
     * 根据配置车型Id+配件名称或者配件名称+OE号匹配商品
     *
     * @param request {"category":"配件名称", "OE":"OE号", "PZCXID":"配置车型ID"}
     * @return
     */
    public Set<SpProduct> compile(SimpleRequest request) {
        JSONObject param = request.getJO();

        // 配件编译
        // 将询价需求编译得到以下数据  - 配件名称 - 商品分类
        Set<SpProduct> spProductSet = new HashSet<>();
        if (param.getJSONObject("category") != null) {
            String PJMCID = param.getJSONObject("category").getString("id");
            param.put("PJMCID", PJMCID);

            //电子目录规则匹配
            String catalogueString = invoke("cm.matching.findByCXDZML", param);
            JSONObject catalogueJSON = JSON.parseObject(catalogueString);
            JSONArray catalogueArray = catalogueJSON.getJSONArray("body");

            //配件名称替换件关系查询
            String mountingsIdJSONString = invoke("cm.matching.findMountingsIDReplace", param);
            JSONObject mountingsIdJSON = JSONArray.parseObject(mountingsIdJSONString);
            JSONArray mountingsIdJSONArray = JSONArray.parseArray(mountingsIdJSON.getString("body"));
            for (int i = 0; i < mountingsIdJSONArray.size(); i++) {
                JSONObject object = mountingsIdJSONArray.getJSONObject(i);
                object.put("PZCXID", param.getString("TDPJMCID"));
                //匹配规则匹配(扩展属性)
                spProductSet.addAll(verifyProperty(object.getString("PJMCID"), param.getString("PZCXID")));

                //循环遍历返回回来的电子目录规则
                for (int k = 0; k < catalogueArray.size(); k++) {
                    JSONObject jsonObject = catalogueArray.getJSONObject(k);
                    //通过电子目录规则获取的OE号与配件名称ID获取商品信息
                    Set<SpProduct> set = spProductRepository.findByPNByCategory(jsonObject.getString("OEID"), mountingsIdJSONArray.getJSONObject(i).getString("TDPJMCID"));
                    spProductSet.addAll(set);
                }

            }

        }


        //OE匹配规则
        if (StringUtils.isEmpty(param.getString("OE"))) return spProductSet;
        // 根据配置车型ID，调用数据中心/老系统接口，进行车型编译
        //  pzcxJsonString {"PZCXID":"配置车型ID", "QCCPMC":"汽车品牌", "QCPPMC":"汽车厂牌"}
        String carTypeConfigJsonString = invoke("cm.matching.findByPZCXID", param);
        JSONObject carTypeConfigJson = JSONArray.parseObject(carTypeConfigJsonString);

        //校验配置车型数据是否为空
        if (carTypeConfigJson.getJSONArray("body").size() == 0)
            return spProductSet;
        JSONObject carTypeConfig = carTypeConfigJson.getJSONArray("body").getJSONObject(0);

        //校验车品牌是否为空
        if (StringUtils.isEmpty(carTypeConfig.getString("QCPPMC"))) return spProductSet;

        param.put("QCPPMC", carTypeConfig.getString("QCPPMC"));
        // 传入{"QCPPMC":"汽车品牌","OE":"零件号"} 调用OE匹配规则方法返回商品数据
        spProductSet.addAll(matchOERule(param));

        return spProductSet;
    }

    /**
     * OE匹配规则
     *
     * @param param {"QCPPMC":"汽车品牌","OE":"零件号"}
     * @return
     */
    public Set<SpProduct> matchOERule(JSONObject param) {
        Set<SpProduct> spProductSet = new HashSet<>();
        //根据OE号获取车品牌与零件号
        JSONArray replacementArray = matchingRuleDao.findByReplaceParts(param);

        JSONArray brandUploading = new JSONArray();
        JSONObject object = new JSONObject();
        object.put("BRAND", param.getString("QCPPMC"));
        object.put("PN", param.getString("OE"));
        replacementArray.add(object);
        //通过替换件关系获取商品数据
        for (int i = 0; i < replacementArray.size(); i++) {
            JSONObject jsonObject = replacementArray.getJSONObject(i);
            //通过车品牌获取车品牌id
            String id = automobileBrandRepository.findByAutomobileBrand(jsonObject.getString("BRAND"));
            //通过零件号与车品牌id得到商品数据
            Set<SpProduct> set = spProductRepository.findByPNByAutomobile(jsonObject.getString("PN"), id);
            for (SpProduct s : set) {
                if (LogicalUtil.in(s.getStandardType(), "Whole", "brandWhole")) {
                    spProductSet.add(s);
                }
            }
            //通过车品牌与零件号查找品牌件关系表获取 品牌与零件号
            JSONArray j = matchingRuleDao.findByBrandPiece(jsonObject);
            brandUploading.addAll(j);
        }
        //通过品牌件关系获取商品数据
        for (int i = 0; i < brandUploading.size(); i++) {
            JSONObject jsonObject = brandUploading.getJSONObject(i);
            SpBrand spBrand = spBrandRepository.findByName(jsonObject.getString("BRAND"));
            if (spBrand != null) {
                Set<SpProduct> set = spProductRepository.findByPNBySpBrand(jsonObject.getString("BRAND_ID"), spBrand);
                spProductSet.addAll(set);
            }

        }

        return spProductSet;

    }


    /**
     * 校验扩展属性
     *
     * @param sPJMCID 配件名称编码
     * @return
     */
    public Set<SpProduct> verifyProperty(String sPJMCID, String sPZCXID) {
        Set<SpProduct> spProductSet = new HashSet<>();

        // 000617=启停蓄电池  000618=蓄电池 000609=轮胎 000678=机油
        if (LogicalUtil.notIn(sPJMCID, "000617", "000618", "000609", "000678")) return spProductSet;

        // 第一步： 根据 配件名称ID + 配置车型 找匹配规则
        // matchRuleArrayString  [{"PPGZ":"匹配规则", "SJLID":"时间文本判断", "ZWMC":"扩展属性字段"."PPZ":"匹配值"}]
        String matchRuleArrayString = invoke("cm.matching.findByPPGZ", MapUtil.mapper("PJMCID", sPJMCID, "PZCXID", sPZCXID));
        JSONObject tempJson = JSONArray.parseObject(matchRuleArrayString);
        JSONArray matchRuleArray = tempJson.getJSONArray("body");
        if (matchRuleArray.size() == 0) return spProductSet;


        // 第二步： 检查对应的扩展属性
        String sql = "";

        // 扩展属性：蓄电池
        if (LogicalUtil.in(sPJMCID, "000618", "000617")) {
            sql = batteryExtendProperty(matchRuleArray);
        }

        // 扩展属性：轮胎
        if ("000609".equals(sPJMCID)) {
            sql = tyreExtendProperty(matchRuleArray);
        }

        //扩展属性：机油
        if ("000678".equals(sPJMCID)) {
            sql = engineOilExtendProperty(matchRuleArray);
        }
        if (StringUtils.isEmpty(sql)) return spProductSet;

        //第三步： 执行匹配规则得到的SQL获取商品ID
        JSONArray SPIDArray = matchingRuleDao.findAatchingRule(sql);
        for (int i = 0; i < SPIDArray.size(); i++) {
            JSONObject json = SPIDArray.getJSONObject(i);
            SpProduct spProduct = spProductRepository.findByIdAndPriceAndQuantity(json.getString("SP_ID"));
            spProductSet.add(spProduct);
        }
        return spProductSet;
    }


    /**
     * 扩展属性：蓄电池
     *
     * @param matchRuleArray 匹配规则
     * @return 扩展属性规则
     */
    private String batteryExtendProperty(JSONArray matchRuleArray) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT SP_ID FROM SP_MAS_ACCUMULATOR_PRODUCT A WHERE 1=1 ");
        String isSql = sql.toString();
        matchRuleArray.stream().forEach(v -> {
            JSONObject temp = (JSONObject) v;
            if (StringUtils.isEmpty(temp.getString("PPZ"))) return;
            String sZDMC = temp.getString("ZWMC");
            if ("参考号".equals(sZDMC)) sZDMC = "reference";
            if ("类型".equals(sZDMC)) sZDMC = "type";

            //调用匹配规则方法将匹配属性进行SQL拼接
            String rule = match(temp, sZDMC);
            sql.append(rule);
        });
        if (isSql.equals(sql.toString())) return null;
        return sql.toString();
    }

    /**
     * 扩展属性：轮胎
     *
     * @param matchRuleArray
     * @return
     */
    private String tyreExtendProperty(JSONArray matchRuleArray) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT SP_ID FROM SP_MAS_TYRE_PRODUCT A WHERE 1=1");
        String isSql = sql.toString();
        matchRuleArray.stream().forEach(v -> {
            JSONObject temp = (JSONObject) v;
            if (StringUtils.isEmpty(temp.getString("PPZ"))) return;
            String sZDMC = temp.getString("ZWMC");
            if ("轮胎规格".equals(sZDMC)) sZDMC = "specification";

            //调用匹配规则方法将匹配属性进行SQL拼接
            String rule = match(temp, sZDMC);
            sql.append(rule);
        });
        if (isSql.equals(sql.toString())) return null;
        return sql.toString();
    }

    /**
     * 机油扩展属性
     *
     * @param matchRuleArray 匹配规则
     * @return
     */
    private String engineOilExtendProperty(JSONArray matchRuleArray) {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT SP_ID FROM SP_MAS_OILY_PRODUCT A WHERE 1=1");
        String isSql = sql.toString();
        for (int i = 0; i < matchRuleArray.size(); i++) {
            JSONObject gz = matchRuleArray.getJSONObject(i);
            if (!Objects.nonNull(gz.get("PPZ"))) {
                continue;
            }
            String rule = match(gz, gz.getString("ZWMC"));
            sql.append(rule);
        }
        if (isSql.equals(sql.toString())) return null;
        return sql.toString();
    }


    /**
     * 扩展属性匹配规则
     *
     * @param gz
     * @param sZDMC 规则属性
     * @return
     */
    public String match(JSONObject gz, String sZDMC) {
        StringBuffer sql = new StringBuffer();
        String sPPZ = gz.getString("PPZ");
        String sSJLXID = gz.getString("SJLXID");
        Integer iPPGZ = gz.getInteger("PPGZ"); //匹配规则(0:等于;1:大于;2:小于;3:大于等于;4:小于等于;5:包含;6:包含于)
        if (iPPGZ == 0) {
            // iPPGZ = 0  等于
            if ("04".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + "= '" + sPPZ + "'");
            } else if ("05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + "=  TO_DATE('" + sPPZ + "', 'YYYY-MM-DD')");
            } else {
                sql.append(" AND " + sZDMC + "= " + sPPZ);
            }

        } else if (iPPGZ == 1) {
            // iPPGZ = 1  大于
            if ("04".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " > '" + sPPZ + "'");
            } else if ("05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " >  TO_DATE('" + sPPZ + "', 'YYYY-MM-DD')");
            } else {
                sql.append(" AND " + sZDMC + " > " + sPPZ);
            }

        } else if (iPPGZ == 2) {
            // iPPGZ = 2  小于
            if ("04".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " < '" + sPPZ + "'");
            } else if ("05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " <  TO_DATE('" + sPPZ + "', 'YYYY-MM-DD')");
            } else {
                sql.append(" AND " + sZDMC + " < " + sPPZ);
            }

        } else if (iPPGZ == 3) {
            // iPPGZ = 3  大于等于
            if ("04".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " >= '" + sPPZ + "'");
            } else if ("05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " >=  TO_DATE('" + sPPZ + "', 'YYYY-MM-DD')");
            } else {
                sql.append(" AND " + sZDMC + " >= " + sPPZ);
            }

        } else if (iPPGZ == 4) {
            // iPPGZ = 4  小于等于
            if ("04".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " <= '" + sPPZ + "'");
            } else if ("05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " <=  TO_DATE('" + sPPZ + "', 'YYYY-MM-DD')");
            } else {
                sql.append(" AND " + sZDMC + " <= " + sPPZ);
            }

        } else if (iPPGZ == 5) {
            // iPPGZ = 5  包含
            if (!"05".equals(sSJLXID)) {
                sql.append(" AND " + sZDMC + " LIKE '%" + sPPZ + "%'");
            }

        } else if (iPPGZ == 6) {
            // iPPGZ = 6  包含于
            String[] item = sPPZ.split(";");
            String sItem = "";
            for (int j = 0; j < item.length; j++) {
                if (sSJLXID.equals("04")) { //文本
                    if (sItem.length() < 1) {
                        sItem = "'" + item[j] + "'";
                    } else {
                        sItem = sItem + ",'" + item[j] + "'";
                    }
                } else {
                    if (sItem.length() < 1) {
                        sItem = item[j];
                    } else {
                        sItem = sItem + "," + item[j];
                    }
                }
            }
            sql.append(" AND " + sZDMC + " IN (" + sItem + ")");
        } else if (iPPGZ == 7) {
            //iPPGZ = 7  模糊匹配
            String[] item = sPPZ.split(";");
            sql.append(" AND ( ");
            if (sSJLXID.equals("04")) {
                for (int j = 0; j < item.length; j++) {

                    if (j != 0) {
                        sql.append(" OR ");
                    }
                    sql.append(sZDMC + " LIKE '%;" + item[j] + ";%'"
                            + " OR " + sZDMC + " LIKE '" + item[j] + ";%' OR " + sZDMC + " LIKE '%;" + item[j] + "'"
                            + " OR " + sZDMC + " = '" + item[j] + "'");
                }
            }

            sql.append(" ) ");

        }
        return sql.toString();
    }


}
